iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 3
0
自我挑戰組

javascript 學習筆記系列 第 3

JavaScript 同步與非同步

  • 分享至 

  • xImage
  •  

Javascript 是同步的語言意指指令由上而下, 一步一步的執行程式碼, 是同步一次只能作一件事, 且依序做

一步一步的執行

基本執行順序, 由上往下執行

consle.log("1");
consle.log("2");
consle.log("3");
/*結果
1
2
3
*/

觀察下段程式碼, getTimem為取得現在時間戳的函數, passTime經過時間函數, block利用while迴圈製作的模擬阻塞函數, 可以觀察到確實block函數阻塞了程式執行, 因為一步一步執行所以同步會有阻塞

const getTime = function () {
  return Date.now();
};
const passTime = function () {
  return Date.now() - timeStart;
};
const block = function (seconds) {
  let time = 1000 * seconds;
  console.log(`阻塞${seconds}秒開始`);
  while (passTime() < time) {}
  console.log(`阻塞${seconds}秒結束`);
};
console.log("步驟1");
let timeStart = getTime();
block(2);
console.log("步驟2");
/*結果
步驟1
阻塞2秒開始
阻塞2秒結束
步驟2
*/

block改用timeout模擬, 發現沒有阻塞作用, 可以發現setTimeout不是同步的

const block = function (seconds) {
  let time = 1000 * seconds;
  console.log("計時器開始");
  setTimeout(function () {
    console.log(`計時器${seconds}秒結束`);
  }, time);
};
console.log("步驟1");
block(2);
console.log("步驟2");
/*結果
步驟1
計時器開始
步驟2
計時器2秒結束
*/

非同步的運作

JavaScript本身是同步的程式語言, 加上環境的API例如瀏覽器提供的setTimeoout與事件觸發才能有非同步產生, 運作方式是將非同步的程式碼放入一個事件佇列(Event queue)中, 等到所有其他同步程式碼執行完後, 在條件觸發下將相關的非同步程式從Event queue取出並執行, 例如setTimeout(funcA, 1000) 就是計時1秒後就執行funcA, 但setTimeout不會對下一行程式碼造成阻塞, 如此一來非同步不會阻塞可以提高JavaScript程式碼的執行效率, 但也因此必須重新考慮程式執行順序, 要正確調整執行順序可以利用JavaScript的一個特性, First Class Function 函數就是一種物件, 所以函數可以當參數使用, 這種機制就是callback, 觀察下面兩塊程式碼, funcA模擬重網路取得資料, setTimeout用來模擬取得資料所費時間, funB要利用取得的資料來作某些事
第1區塊程式看funcA之後執行funcB, 乍看順序沒問題, 但因為非同步關係導致整體執行順序與要求不同

let funcA = function () {
  console.log("A開始取得資料");
  setTimeout(function () {
    console.log("A取得資料結束");
  }, 1000);
};
let funcB = function () {
  console.log("利用A取的資料做事");
};
funcA();
funcB();
/*結果 順序有問題
A取得資料結束
利用A取的資料做事
A取得資料結束
*/

第2塊程式碼, 將funcB 當作funcA參數傳入, 取得資料結束後就執行funcB, 這樣執行順序符合要求

let funcA = function (callback) {
  console.log("A開始取得資料");
  setTimeout(function () {
    console.log("A取得資料結束");
    callback();
  }, 1000);
};
let funcB = function () {
  console.log("利用A取的資料做事");
};
funcA(funcB);
/*結果 順序正確
A取得資料結束
A取得資料結束
利用A取的資料做事
*/

callback的問題

當有大量的非同步又必須依照順序來執行時, 就可能會出現多層callback, 俗稱的callback hell, 這會造成痛苦的debug, 這問題可以用ES6提供了Promise物件來避免


上一篇
安裝nodejs
下一篇
JavaScript AJAX
系列文
javascript 學習筆記4
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言